package org.smallreunion.service;

import org.slim3.datastore.Datastore;
import org.slim3.memcache.Memcache;
import org.smallreunion.meta.AuthTokenMeta;
import org.smallreunion.model.AuthToken;
import org.smallreunion.model.Member;
import org.smallreunion.util.RandomUtil;
import org.smallreunion.util.SecurityUtil;
import org.smallreunion.var.LoginInfo;

import com.google.appengine.api.datastore.Key;

/**
 * AuthTokenService
 *
 * @author Sinmetal
 *
 */
public class AuthTokenService {

    private AuthTokenMeta meta = AuthTokenMeta.get();

    /**
     * AuthTokenString作成
     *
     * @param memberKey
     * @return
     */
    public String createAuthTokenString(Key memberKey) {
        StringBuilder builder = new StringBuilder();
        builder.append(Datastore.keyToString(memberKey));

        final int TRAY_MAX_COUNT = 1000;
        for (int i = 0; i < TRAY_MAX_COUNT; i++) {
            builder.append(RandomUtil.nextLong());
            String token = SecurityUtil.encrypt(builder.toString());

            Key key = AuthToken.createKey(token);
            AuthToken authToken = Datastore.getOrNull(meta, key);
            if (authToken == null) {
                return token;
            }
        }
        throw new RuntimeException("重複しないTokenの作成に失敗しました。");
    }

    /**
     * put loginInfo
     *
     * @param token
     * @param info
     * @param timeout
     * @return
     */
    public Key putLoginInfo(String token, LoginInfo info, int timeout) {
        String memcacheKey = createAuthTokenMemcacheKey(token);
        AuthToken authToken = AuthToken.getInstance(token, info, timeout);
        Key key = Datastore.put(authToken);
        Memcache.put(memcacheKey, info);
        return key;
    }

    /**
     * get logininfo in memory
     *
     * @param token
     * @return
     */
    public LoginInfo getLoginInfoInMemory(String token) {
        String memcacheKey = createAuthTokenMemcacheKey(token);
        if (Memcache.contains(memcacheKey)) {
            return Memcache.get(memcacheKey);
        }
        return null;
    }

    /**
     * get loginInfo
     *
     * @param token
     * @return
     */
    public LoginInfo getLoginInfo(String token) {
        Key key = AuthToken.createKey(token);
        AuthToken authToken = Datastore.getOrNull(meta, key);
        if (authToken == null) {
            return null;
        }
        Key memberKey = authToken.getMemberKey();
        Member member = Datastore.getOrNull(Member.class, memberKey);
        if (member == null) {
            return null;
        }
        LoginInfo loginInfo = LoginInfo.getInstance(member);
        Memcache.put(token, loginInfo);
        return loginInfo;
    }

    /**
     * delete authToken
     *
     * @param token
     */
    public void deleteAuthToken(String token) {
        String memcacheKey = createAuthTokenMemcacheKey(token);
        Memcache.delete(memcacheKey);
        Key key = AuthToken.createKey(token);
        Datastore.delete(key);
    }

    /**
     * create authToken memcacheKey
     *
     * @param token
     * @return
     */
    private String createAuthTokenMemcacheKey(String token) {
        return this.getClass().getCanonicalName() + token;
    }
}
